// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#include "SmartMovieSceneSectionExtensions.h"
#include "MovieSceneSection.h"
#include "MovieScene.h"
#include "Channels/MovieSceneChannelProxy.h"
#include "Channels/MovieSceneChannel.h"


int32 USmartMovieSceneSectionExtensions::SmGetRow(UMovieSceneSection* Section)
{
	return Section->GetRowIndex();
}

void USmartMovieSceneSectionExtensions::SmSetRow(UMovieSceneSection * Section, int32 Index)
{
	Section->SetRowIndex(Index);
}

void USmartMovieSceneSectionExtensions::SmSetRange(UMovieSceneSection * Section, int32 Start, int32 End)
{
	UMovieScene* MovieScene = Section->GetTypedOuter<UMovieScene>();
	if (MovieScene)
	{
		const FFrameRate DisplayRate = MovieScene->GetDisplayRate();
		TRange<FFrameNumber> NewRange;
		NewRange.SetLowerBound(TRangeBound<FFrameNumber>::Inclusive(ConvertFrameTime(Start, DisplayRate, MovieScene->GetTickResolution()).FrameNumber));
		NewRange.SetUpperBound(TRangeBound<FFrameNumber>::Exclusive(ConvertFrameTime(End, DisplayRate, MovieScene->GetTickResolution()).FrameNumber));

		if (NewRange.GetLowerBound().IsOpen() || NewRange.GetUpperBound().IsOpen() || NewRange.GetLowerBoundValue() <= NewRange.GetUpperBoundValue())
		{
			Section->SetRange(NewRange);
		}
		else
		{
			FFrame::KismetExecutionMessage(TEXT("Invalid range specified"), ELogVerbosity::Error);
		}
	}
}

TArray<int32> USmartMovieSceneSectionExtensions::SmGetRange(UMovieSceneSection * Section)
{
	TArray<int32> FrameRange;
	const UMovieScene* MovieScene = Section->GetTypedOuter<UMovieScene>();
	const FFrameRate DisplayRate = MovieScene->GetDisplayRate();
	const int32 Start = ConvertFrameTime(Section->GetRange().GetLowerBoundValue(), MovieScene->GetTickResolution(), DisplayRate).FloorToFrame().Value;
	const int32 End = ConvertFrameTime(Section->GetRange().GetUpperBoundValue(), MovieScene->GetTickResolution(), DisplayRate).FloorToFrame().Value;
	FrameRange.Add(Start);
	FrameRange.Add(End);
	return FrameRange;
}

void USmartMovieSceneSectionExtensions::SmSetLocked(UMovieSceneSection * Section, bool bIsLocked)
{
	Section->SetIsLocked(bIsLocked);
}

void USmartMovieSceneSectionExtensions::SmSetActive(UMovieSceneSection * Section, bool bIsActive)
{
	Section->SetIsActive(bIsActive);
}

int32 USmartMovieSceneSectionExtensions::SmGetStartFrameOffset(UMovieSceneSection * Section)
{
	const UMovieScene* MovieScene = Section->GetTypedOuter<UMovieScene>();
	const FFrameRate DisplayRate = MovieScene->GetDisplayRate();
	TOptional<FFrameTime> FrameTime = Section->GetOffsetTime();
	return ConvertFrameTime(FrameTime.GetValue(), MovieScene->GetTickResolution(), DisplayRate).FloorToFrame().Value;
}

int32 USmartMovieSceneSectionExtensions::SmGetFrameNumber(UMovieSceneSection * Section, int32 Frame)
{
	const UMovieScene* MovieScene = Section->GetTypedOuter<UMovieScene>();
	const FFrameRate DisplayRate = MovieScene->GetDisplayRate();
	const FQualifiedFrameTime FrameTime = FQualifiedFrameTime(ConvertFrameTime(Frame, DisplayRate, MovieScene->GetTickResolution()) ,DisplayRate);
	return FrameTime.Time.GetFrame().Value;
}
